﻿using IOP.SgrA.GLSL;
using IOP.SgrA.SilkNet.Vulkan;
using IOP.SgrA.SilkNet.Vulkan.Scripted;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace VkSample1213
{
    [ShaderVersion("460")]
    [GLSLExtension("GL_ARB_separate_shader_objects : enable")]
    [GLSLExtension("GL_ARB_shading_language_420pack : enable")]
    public partial class LandFrag : GLSLFrag
    {
        [UniformBuffer(0, 0, DescriptorSetTarget.RenderObject)]
        public ConstantVals Vals { get; set; }
        [SampledImage(1, 1, DescriptorSetTarget.RenderObject)]
        public sampler2D TXued {  get; set; }
        [SampledImage(1, 2, DescriptorSetTarget.RenderObject)]
        public sampler2D TCaodi {  get; set; }
        [ShaderInput(0)]
        public vec2 InTexCoor {  get; set; }
        [ShaderInput(1)]
        public float LandHeight {  get; set; }
        [ShaderInput(2)]
        public vec4 PLocation { get; set; }
        [FragOutput(0, false)]
        public vec4 OutColor {  get; set; }

        float SlabY = 60.0f;//雾平面的高度
        float QFheight = 5.0f;//雾平面起伏高度
        float WAngleSpan = 12 * 3.1415926f;//雾的总角度跨度

        float TjFogCal(vec4 pLocation)
        {//计算体积雾浓度因子的方法
            float xAngle = pLocation.x / 960.0f * WAngleSpan;//计算出顶点X坐标折算出的角度
            float zAngle = pLocation.z / 960.0f * WAngleSpan;//计算出顶点Z坐标折算出的角度
            float slabYFactor = sin(xAngle + zAngle + Vals.startAngle) * QFheight;//联合起始角计算出角度和的正弦值
                                                                                          //求从摄像机到待处理片元的射线参数方程Pc+(Pp-Pc)t与雾平面交点的t值
            float t = (SlabY + slabYFactor - Vals.uCamaraLocation.y) / (pLocation.y - Vals.uCamaraLocation.y);
            //有效的t的范围应该在0~1的范围内，若不存在范围内表示待处理片元不在雾平面以下
            if (t > 0.0 && t < 1.0)
            {//若在有效范围内则
             //求出射线与雾平面的交点坐标
                float xJD = Vals.uCamaraLocation.x + (pLocation.x - Vals.uCamaraLocation.x) * t;
                float zJD = Vals.uCamaraLocation.z + (pLocation.z - Vals.uCamaraLocation.z) * t;
                vec3 locationJD = new vec3(xJD, SlabY, zJD);
                float L = distance(locationJD, pLocation.xyz);//求出交点到待处理片元位置的距离
                float L0 = 20.0f;
                return L0 / (L + L0);//计算体积雾的雾浓度因子
            }
            else
            {
                return 1.0f;//若待处理片元不在雾平面以下，则此片元不受雾影响
            }
        }

        public override void main()
        {
            float height1 = 90;//混合纹理起始高度
            float height2 = 180;//混合纹理结束高度
            vec4 colorCaodi = textureLod(TCaodi, InTexCoor, 0.0f);//采样出草地颜色
            vec4 colorSand = textureLod(TXued, InTexCoor, 0.0f);//采样出雪地颜色
            if (LandHeight < height1)
            {//绘制草地
                OutColor = colorCaodi;
            }
            else if (LandHeight < height2)
            {//绘制混合颜色
                float radio = (LandHeight - height1) / (height2 - height1);
                OutColor = mix(colorSand, colorCaodi, 1 - radio);
            }
            else
            {//绘制雪地
                OutColor = colorSand;
            }
            float fogFactor = TjFogCal(PLocation);//计算雾浓度因子
            OutColor = fogFactor * OutColor + (1.0f - fogFactor) * new vec4(0.9765f, 0.7490f, 0.0549f, 0.0f); //给此片元最终颜色值
        }
    }
}
